#include "ServiceGraph.h"
#include "IwdUtils.h"
#include <cstring>

struct string
{
	char *content;
};

bool operator<( string first, string second)
{
	return (strcmp(first.content, second.content)<0);
}
std::map<string , Service *> nodesMap;
std::map<string, int> indicesMap;

ServiceGraph::ServiceGraph(void)
{
}

ServiceGraph::~ServiceGraph(void)
{
}


void ServiceGraph::buildGraph(xml::XmlData &data)
{
	xml::XmlNode *root = data.getRoot();

	if(!root)
		return;

	int rootSize = root->children.size();
	for(int i=0; i<rootSize ; ++i)
		if(!strcmp(root->children[i]->tag[0], "service"))
		{
			xml::XmlNode *service = root->children[i];
			int size = service->children.size();
			Service *serv ;
			serv = new Service;
			for(int k=0; k < size; ++k)
			{
				int s;
				for(s = IwdUtils::CODE; s < IwdUtils::FIRST_UNUSED && strcmp(IwdUtils::serviceStrings[s], service->children[k]->tag[0]); ++s);
				switch(s)
				{
				case IwdUtils::CODE:
					(*serv).code = service->children[k]->content[0];
					break;
				case IwdUtils::NAME:
					(*serv).name = service->children[k]->content[0];
					break;
				case IwdUtils::INPUT:
					(*serv).input.push_back(service->children[k]->content[0]);
					break;
				case IwdUtils::OUTPUT:
					(*serv).output.push_back(service->children[k]->content[0]);
					break;
				case IwdUtils::LEVEL:
					(*serv).level = atoi(service->children[k]->content[0]);
					break;
				case IwdUtils::COST:
					(*serv).cost = atof(service->children[k]->content[0]);
					break;
				case IwdUtils::RELIABILITY:
					(*serv).reliability = atof(service->children[k]->content[0]);
					break;		
				case IwdUtils::AVAILABILITY:
					(*serv).availability = atof(service->children[k]->content[0]);
					break;
				case IwdUtils::RESPONSETIME:
					(*serv).responsetime = atof(service->children[k]->content[0]);
					break;
				case IwdUtils::QOS:
					(*serv).qos = atof(service->children[k]->content[0]);
					break;
				case IwdUtils::FIRST_UNUSED:
					break;
				}
			}
			this->nodes.push_back(serv);
			string name;
			name.content = (*serv).name;
			nodesMap[name] = serv;
			indicesMap[name] = this->nodes.size()-1;
		}
		else if(!strcmp(root->children[i]->tag[0], "cluster"))
		{
			xml::XmlNode *service = root->children[i];
			int size = service->children.size();
			const char *clusterStrings[] = {"level", "name", "memberservice"};
			Cluster *clust;
			clust = new Cluster;
			for(int k=0; k < size; ++k)
			{
				int s;
				for(s = 0 ; s < 3 && strcmp(clusterStrings[s], service->children[k]->tag[0]); ++s);
				switch(s)
				{
				case 0:
					//level
					(*clust).level = atoi(service->children[k]->content[0]);
					break;
				case 1:
					//name
					(*clust).name = service->children[k]->content[0];
					break;
				case 2:
					//member service
					Service *aux;
					string nume;
					nume.content = service->children[k]->content[0];
					aux = nodesMap[nume];
					(*clust).memberServices.push_back(aux);
					nodesMap[nume]->cluster = clust;
					clusters.push_back(clust);
					break;
				}
			}
		}
		else if(!strcmp(root->children[i]->tag[0], "link"))
		{
			xml::XmlNode *service = root->children[i];
			int size = service->children.size();
			const char *linkStrings[] = {"from", "to", "score", "pair"};
			Link *link;
			link = new Link;
			for(int k=0; k < size; ++k)
			{
				int s;
				for(s = 0; s < 4 && strcmp(linkStrings[s], service->children[k]->tag[0]); ++s);
				string name ;
				name.content = service->children[k]->content[0];
				switch(s)
				{
				case 0:
					//from
					link->i = indicesMap[name];
					break;
				case 1:
					//to
					link->j = indicesMap[name];
					break;
				case 2:
					//score
					link->score = atof(name.content);
					break;
				case 3:
					//pair
					std::pair<char * , char *> inout;
					inout.first = strtok(name.content, ",");
					inout.second = strtok(NULL, ",");
					link->pairs.push_back(inout);
					break;
				}
			}
			edges.push_back(link);
		}
}

void ServiceGraph::computeQoS()
{
	std::vector <Service *>::iterator it;
	double const weights[] = {0.15, 0.25, 0.45, 0.15};

	for(it = nodes.begin(); it != nodes.end(); ++it)
	{
		(*it)->qos = (*it)->availability * weights[0] + (*it)->reliability * weights[1] + (*it)->cost * weights[2] + (*it)->responsetime * weights[3];
	}
}

